4 Changes to the VHDL type system

4.1 Class types

The class type is the primary data abstraction in Objective VHDL. It represents a collection of class attributes (data fields) together with associated functionality provided by subprograms (methods). The set of subprograms defining the class interface and their implementations may differ depending on the instantiation of the class type as a signal, [shared] variable, or constant. On the other hand, the set of data fields defining the individual local state of an instance of a class type is not affected by the kind of instantiation. Thus, a value of a class type can be assigned to a signal as well as a variable of that class type, and in constant definitions. Inheritance supports reuse and extension of class types. An object in the object-oriented sense is a value of a class type. Such values can be stored in VHDL objects, i.e. signals, variables, and constants. Polymorphism enables uniform handling of objects related by inheritance. In particular, existing source code can handle additional derived classes without modification.

Anchor: A class type definition consists of class type declaration (interface) and class type body. The body must be preceded by a declaration within the same declarative region. By adding the class type definition to the VHDL type definition, the object-oriented class type is anchored in the type system of Objective VHDL.

type_definition ::=
		  scalar_type_definition
		| composite_type_definition
		| access_type_definition
		| file_type_definition
		| class_type_definition             -- new
class_type_definition ::=
		  class_type_declaration
		| derived_class_type_declaration
		| class_type_body

4.2 Declaration of class types

In the class type declaration, an interface of VHDL subprograms being visible outside the class type is declared. Also class attributes[1] are declared in the interface, but access to them is limited to bodies of the class and its subclasses which can be derived by a new ... with notation similar to derived entities. The keyword abstract can be used to declare an abstract class or abstract derived class which is not to be instantiated.

class_type_declaration ::=
		[ abstract ] class
			[ formal_generic_clause ]
			{ class_type_declarative_item }
		end class [ class_type_simple_name ]
derived_class_type_declaration ::=
		new [ abstract ] class class_type_name with
			[ formal_generic_clause ]
			{ class_type_declarative_item }
		end class [ class_type_simple_name ]
class_type_declarative_item ::=
		  class_attribute_declaration
		| class_type_common_declarative_item
		| class_type_object_configuration
class_type_common_declarative_item ::=
		  type_declaration
		| subtype_declaration
		| constant_declaration
		| subprogram_declaration
		| alias_declaration
		| use_clause
	

If a simple name appears at the end of a (derived) class type declaration, it must repeat the identifier of the type declaration in which the class type declaration is included.

Inheritance relationship: The class type denoted by the identifier used in a derived class declaration is called direct descendant of or derived from the class type denoted by class_type_name. Vice versa, class_type_name is called direct ancestor of or extended by the class type 'identifier'. An class type T' is descendant of a class type T if T' is a direct descendant or if its ancestor is a descendant of T. A class type T is an ancestor of a class type T' if T is a direct ancestor or if one of its descendants is an ancestor of T'. An indirect descendant (ancestor, resp.) is a descendant (ancestor, resp.) which is not a direct descendant (ancestor, resp.)

A class type declaration consists of common declarative item and specific declarations targeting an instantiation of the class type as signal, variable, or constant (cf. class type configuration, 4.2.7). The declaration of data fields is common to all instantiations of a class so that class-typed values can be assigned from signals to variables as well as vice versa. The subprogram interface and/or implementation on the other hand may depend on and is selected by the kind of VHDL object (signal, variable, constant) that stores a class-typed value.

Example: Abstract classes serving as parents of all messages to (replies from, resp.) the entity Memory of section 3.2.2

type MemoryRpl is abstract class
end class MemoryRpl;
type MemoryMsg is abstract class
		for signal
			procedure dispatch( signal Reply : out MemoryRpl'CLASS );
		end for;
end class MemoryMsg;

4.2.1 Generic clause

In combination with class and derived class types, generics allow to parameterize declarations made within the class type. A (derived) class type containing a generic clause is said to be a generic class type. A declared generic constant is visible within the complete containing class type (see 4.4.2). Inheritance of generics in class types is defined like for entities (cf. 3.2.1):

Effective generic list: The effective generic list of a (non-derived) class type declaration is the generic list defined in the class type. The set of generic names declared in a derived class type must be disjoint from the effective generic list of its ancestor. The effective generic list of the derived class type is then formed by appending to its direct ancestor's effective generic list the generic list declared in the derived class.

4.2.2 Type declaration

The syntactic and semantic rules for type declarations are transferred from the LRM, section 4.1. The declared type is visible within the enclosing class type from the point of its declaration (see 4.4.2).

4.2.3 Subtype declaration

The syntactic and semantic rules for subtype declarations are transferred from the LRM, Section 4.2. The declared subtype is visible within the enclosing class type from the point of its declaration (see 4.4.2).

4.2.4 Class attribute declaration

Declarations of data fields (attributes in oo-terminology)--which are not of class constant--of class types are preceded by the keywords class attribute. Each value of a class type has its own storage to hold the values of its class attributes, representing the internal state of an object. Within each class type, the identifiers of all class attribute declarations must be distinct. But in a derived class, an identifier may be used again (see 4.4.3). The subtype_indication used in the class attribute declaration must not denote an unconstrained type.

class_attribute_declaration ::=
		class attribute identifier : subtype_indication [ := expression ] ;

Note: Semantics of the class attribute inside a class type specification differ from VHDL attributes.

Rationale: Data elements of the class type should be declared similarly to signals, variables, or constants, as opposed to record element declarations. But the choice of either signal, variable, or constant is not convenient since signals as well as variables and constants are to be declared as class types. Hence the class attribute declaration is introduced.

Note: In case subtype_indication denotes a class-wide type the initialization is stipulated (not optional), see 4.5.2.

Rationale: By the stipulated initialization of class attributes of class-wide type the actual class type is defined explicitly by the called constructor function (expression). Without the initialization it is not clear what the initial actual type of class attribute of class-wide type is.

Note: Names of class attributes must not be used in the declaration of other items in the class type declaration because class attribute values are not globally static.

Example: Message ReadMsg and the corresponding reply ReadRpl

-- a read message includes the memory address (Addr) to be read
type ReadMsg is new class MemoryMsg with
		class attribute Addr : Natural;
end class ReadMsg;
-- a reply to a read message includes the value which has been read
type ReadRpl is new class MemoryRpl with
		class attribute Value : MemDatum'CLASS;
end class ReadRpl;

4.2.5 Constant declaration

The constant declaration declares data elements of class constant with a constrained type. When the initialization expression for the constant declaration is missing, the constant is said to be a deferred constant. The value of a deferred constant must be defined in a corresponding constant declaration inside the corresponding class type body for each declarative region (see 4.4.1) in which the deferred constant is declared.

4.2.6 Subprogram declaration

Each subprogram declared in a class type declaration declares an operation that works on a single object of the class type. The object is specified by a prefix when calling a subprogram (see 4.4.3, 4.6.1).

Subprograms declared as common declarative items of the class type declaration, called common subprograms, are common for all instantiations of the class (signal, variable, constant). So they must have an implementation which works on all kinds of objects[2] (see 4.3.6).

The interface declaration of a subprogram declared in a class type may contain formal parameters of the same class type. In case of a function, also the type of the return parameter can be of the same class type. Any other use of the class type name in its own declaration is forbidden.

Rationale: To allow the implementation of subprograms which perform n-ary operations on the class type, it is necessary to permit the use of the class type name within its own declarative region. (cf. Shared Variables LCS, Section 2.3.1.1)

Generics of generic class types must not be used in a subprogram declaration of a [derived] class type declaration or body.

Rationale: Subprograms form the interface of a (generic) class type. All class subtypes created from a generic class type shall have the same interface or, in other words, the same operations that may be invoked with objects of these subtypes. This is required to allow subprogram calls with objects of class-wide type, which must not depend on the value of any generic.

Note: It is possible to use unconstrained types such as unconstrained array types to declare subprogram parameters; no need to constrain then using a generic.

4.2.7 Class type object configuration

The class type object configuration contains declarations which are exclusively available for instantiation of the class type as variable, signal, constant, or a combination of them.

class_type_object_configuration ::=
		for object_specification { , object_specification }
			{ class_type_common_declarative_item }
		end for ;
object_specification ::=
		signal | variable | constant

In a given list of object specifications after the keyword for, object specification keywords (signal, variable, constant) must not be repeated; i.e. each of them may occur once at maximum.

The class configuration distinguishes the subprograms working on a class type instantiation as signal from a class type instantiation as variable or constant, respectively; see definition of declarative region (4.4.1) and class subprogram call by selection (4.6.1).

Note: It is allowed to use the same names for subprograms in the signal, variable and constant part which have different implementations. For consistency reasons it is recommended to do this only if both subprograms implement similar functionality.

Rationale: If two subprograms--e.g. one working on signals the other working on variables--implement similar functionality, the use of the same subprogram names supports self documentation and comprehensibility of code.

Note: The number and meaning of the subprogram declarations in the different class configuration parts may differ completely.

Note: Class attribute declarations are not permitted inside a class type configuration since all attributes should be common to signals and variables. Class type configurations must not be nested.

4.2.8 Alias declaration

The syntactic and semantic rules for alias declarations are transferred from the LRM, section 4.3.3.

4.2.9 Use clause

The syntactic and semantic rules for use clauses are transferred from the LRM, section 10.4, with the restrictions stated in sections 3.5.2 and 4.4.4 of this document.

4.2.10 Inheritance

Inheritance of declarations is defined through visibility rules in 4.4.3.

Example: Data types to be stored in a memory.

type MemDatum is abstract class
end class;
type Number is new abstract class MemDatum with
		procedure add( a, b : Number'CLASS );
		procedure sub( a, b : Number'CLASS );
end class Number;
type Complex is new class Number with
		class attribute Re : Real;
		class attribute Im : Real;
		impure function RealPart return Real;
		impure function ImagPart return Real;
end class Complex;

4.3 Declaration of class bodies

The class body primarily comprises subprogram body definitions of the subprograms declared in a class type declaration. Moreover it allows to declare items that are only visible in the class body itself ("private").

class_type_body ::=
		class body
			{ class_body_declarative_item }
		end class body [ class_type_simple_name ]
class_body_declarative_item ::=
		  class_attribute_declaration
		| class_body_common_declarative_item
		| class_body_object_configuration
		| class_body_entity_configuration
class_body_common_declarative_item ::=
		  type_declaration
		| subtype_declaration
		| constant_declaration
		| subprogram_declaration
		| subprogram_body
		| alias_declaration
		| use_clause

If a simple name appears at the end of a class body definition, it must repeat the identifier of the type declaration in which the class body definition is included.

An error is generated if a class body definition is not preceded by a corresponding class type declaration in the same immediate declarative region. A non-abstract class must be succeeded in its immediate declarative region by a corresponding class body definition. An abstract class may, but need not have a body.

4.3.1 Type declaration

The syntactic and semantic rules for type declarations are transferred from the LRM, section 4.1. The declared type is visible from the point of its declaration within the enclosing class type body. It is not visible in derived classes.

4.3.2 Subtype declaration

The syntactic and semantic rules for subtype declarations are transferred from the LRM, section 4.2. The declared subtype is visible from the point of its declaration within the enclosing class type body. It is not visible in derived classes.

4.3.3 Class attribute declaration

See section 4.2.4. As opposed to class attributes declared in a class type declaration, class attributes declared in a class type body are not visible to derived classes.

4.3.4 Constant declaration

See section 4.2.5. As opposed to constants declared in a class type declaration, constants declared in a class type body are not visible to derived classes.

4.3.5 Subprogram declaration

See section 4.2.6. Subprograms declared in a class type body are not visible to derived classes, and they are class type internal ("private") subprograms. They cannot be called from outside the class because their interface is not declared in the class type declaration (see 4.4.3).

4.3.6 Subprogram body

Bodies of common subprograms (cf. 4.2.6) can (but do not need to) be defined as declarative items of the class body. This means the implementation of the subprograms does not depend on the class of instantiation (variable, signal, constant) of the class type.

In the common subprogram bodies, class attributes must be used like constants. In particular, they must not occur as the target of an assignment, and they must not be associated as an actual with a formal parameter of class variable or signal.

In the body of a pure function declared in a class, the class attributes may be read.

Rationale: Without this extension of the notion of pureness, a function of a class that shall have direct access to the class attributes would necessarily have to be declared as impure, which makes the use of functions infeasible with VHDL'87 back ends. Even with this extension, two invocations of a pure function with the same actual parameter values and prefixed by objects which have the same state (i.e. attribute values) will always return the same result value.

4.3.7 Class body object configuration

A class body object configuration contains declarations which are specific to class instantiations as signal, variable, or constant.

class_body_configuration ::=
		for object_specification { , object_specification }
			{ class_body_common_declarative_item }
		end for ;
object_specification ::=							-- same as above
		signal | variable | constant

In a given list of object specifications after the keyword for, object specification keywords (signal, variable, constant) must not be repeated; i.e. each of them may occur once at maximum.

In particular, the class configuration implementation distinguishes the subprogram bodies working on a class type instantiation as signal from a class type instantiation as variable or constant; cf. 4.2.7.

Subprogram bodies declared in a class body configuration for signal can and must use the class attributes as if they were signals. Subprogram bodies declared in a class body configuration for variable can and must use the class attributes as if they were variables. Subprogram bodies declared in a class body configuration for constant can and must use the class attributes as if they were constants.

Note: Class attributes can be target of an assignment, actual parameter in a subprogram call, a primary in an expression. The above rule determines for instance the operator to be used in assignments to class attributes and the parameter passing to subprograms (e.g. in a for signal configuration, a class attribute must not be associated as an actual parameter with a formal parameter of kind variable).

Example: Implementation of class Complex. Note that if add had been declared in signal- and variable-specific parts of class Number, no for constant would be required.

-- Note: procedure sub must be implemented similarly as procedure add.
type Complex is class body
		impure function RealPart return Real is
		begin
			return Re;
		end;
		impure function ImagPart return Real is
		begin
			return Im;
		end;
		for signal
			procedure add( a, b: Number'CLASS ) is
				variable a_casted, b_casted : Complex;
			begin
				a_casted := a;			-- a run-time error is produced if the numbers
				b_casted := b;			-- to be added are not of type Complex.
				Re <= a_casted.RealPart + b_casted.RealPart;
				Im <= a_casted.ImagPart + b_casted.ImagPart;
			end;
		end for;
		for variable
			procedure add( a, b: Number'CLASS ) is
				variable a_casted, b_casted : Complex;
			begin
				a_casted := a;			-- a run-time error is produced if the numbers
				b_casted := b;			-- to be added are not of type Complex.
				Re := a_casted.RealPart + b_casted.RealPart;
				Im := a_casted.RealPart + b_casted.RealPart;
			end;
		end for;
		for constant
			procedure add( a, b: Number'CLASS ) is
			begin
				report "Complex.add: Not available for constant target."
				severity failure;
			end;
		end for;
end class body Complex;

4.3.8 Class body entity configuration

Inside a class body entity configuration, the declarations of a given entity are visible. Whenever a subprogram declared in the class type is called from that entity or from an architecture of that entity, a corresponding subprogram body of the class body entity configuration will be executed if declared. If the subprogram body is not declared in the class body entity configuration, the implementation is taken from the other part of the class body.

class_body_entity_configuration ::=
		for entity entity_name
			{ class_body_entity_configuration_declarative_item }
		end for ;
class_body_entity_configuration_declarative_item ::=
		  class_body_common_declarative_item
		| class_body_object_configuration

Note: There may exist several class body entity configurations inside one class type body. They may even reference the same entity.

Example:

type ReadMsg is class body
		for signal
			procedure dispatch( signal Reply : out MemoryRpl'CLASS ) is
			begin
				report "ReadMsg.dispatch not implemented in this place."
				severity error;
			end;
		end for;
		for entity Work.Memory
			for signal
				procedure dispatch( signal Reply: out MemoryRpl'CLASS) is
					variable help : MemDatum'CLASS;
					variable R : ReadRpl;
				begin
					Read( Addr, help );
					R.set( help );
					Reply <= R;
				end;
			end for;
		end for;
end class body ReadMsg;

4.3.9 Alias declaration

The syntactic and semantic rules for alias declarations are transferred from the LRM, section 4.3.3.

4.3.10 Use clause

The syntactic and semantic rules for use clauses are transferred from the LRM, section 10.4, with the restrictions stated in sections 3.5.2 and 4.4.4 of this document.

4.3.11 Inheritance

Inheritance of declarations to a class body of a derived class is defined through the inclusion of its class type declaration in its declarative region and the visibility rules (see 4.4.3). Note that declarations of class bodies of derived class types do not have visibility of the declarations of the ancestors' bodies.

4.4 Scope and visibility

4.4.1 Declarative regions

A class type declaration constitutes the following declarative regions together with the corresponding class body definition (if any):

The ordering of the declarative items within a declarative region is defined by the ordering within the class type declaration or class body declaration, respectively.

In the declarative regions formed by an abstract class, a subprogram declaration does not need to be succeeded (but it may be succeeded) by a corresponding subprogram body. In the declarative regions formed by a class that is not abstract, every subprogram declaration must have a corresponding subprogram body.

4.4.2 Scope of declarations

Declarations appearing in a declarative region of a class type are directly visible from the point of their declaration to the end of the declarative region.

4.4.3 Visibility

Subprogram declarations appearing as common declarative items of a class type declaration are visible by selection with a prefix denoting a constant, variable, or signal of the class type or of a descendant. Subprogram declarations appearing as declarative items of a class type configuration for signal (variable, constant, resp.) are visible by selection with a prefix denoting a signal (variable, constant, resp.) of the class type or of a descendant. Any other declarations appearing in a class type declaration or body are not visible by selection from other than derived classes (see special rules below).

Rationale: Support encapsulation. Class attributes are protected against access by selection. The subprograms declared in the class type declaration provide the only interface to objects of class type. They can be called with an object prefix (see 4.6.1).

Names declared by declarative items inside one of the declarative regions of a class type declaration alone (i.e. without the class body) are implicitly declared in the corresponding declarative region of the derived class. Also implicit declarations are inherited in this way. To apply classical VHDL visibility and overloading rules, the declarative regions formed by a direct ancestor class type declaration alone (i.e. without the class body) are considered as the immediate enclosing regions of their corresponding declarative regions formed by the derived class.

An implicit declaration of a non-overloadable item is hidden by an explicit declaration using the same identifier. An implicit declaration of an overloadable item is hidden by an explicit declaration that has the same parameter and return type profile as the implicit item. If an overloaded subprogram is to be invoked with an object of a class-wide type (see 4.5.1, 4.5.2), the overloaded subprograms must have syntactically identical formal parameter lists.

Rationale: Make sure that the interface of subprograms is pertained exactly during inheritance. To ensure that polymorphic subprogram calls can always be bound to a subprogram implementation, an inherited subprogram should not be hidden by a subprogram that cannot be overloaded because it differs in e.g. only a parameter mode.

Note: Inherited class attribute declarations may be hidden. In the language architecture document, overriding redeclaration of attributes had been forbidden because a change of their types would affect inherited code. In contrast, a hidden declaration continues to exist and be accessed by inherited code. The hiding declaration exists in parallel and will be used by the new code. This helps to make coding more independent from the choice of identifiers in related classes.

Inside a class, a declaration from the class declaration of an ancestor is visible by selection using the ancestor's class_type_name as prefix. Declarations from the class declaration itself are visible by selection using the name of the class as a prefix.

Note: This allows to access declarations that have been hidden, for instance an attribute having the same name as a formal parameter of a subprogram.

4.4.4 Use clauses

Use clauses must not be used in conjunction with a prefix selecting a class type.

Rationale: Inside a derived class, inherited declarations are directly visible if not hidden (4.4.3). Outside, data fields are not subject to selection according to 4.4.3. Subprograms are not to be made directly visible by a use clause because a prefix is required to denote the object to which a subprogram is invoked.

4.5 Use of class types

4.5.1 Type declarations

An incomplete type may be completed as a class type.

From each class type T, a corresponding class-wide type can be deduced by application of the attribute 'CLASS (see 4.8.2). T'CLASS denotes the set of types including T and all descendants of T. If T is a generic class type and the 'CLASS attribute is applied to it, a generic map need not and must not be supplied. The 'CLASS attribute must not be used with a class subtype as defined below.

Generic class types are considered similar to unconstrained types. From a generic class type, a non-generic (similar: constrained) subtype can be declared by supplying a generic map aspect and, optionally, a resolution function, using the second form shown below:

subtype_indication ::=
		  [ resolution_function_name ] type_mark [ constraint ]       -- VHDL'93
		| [ resolution_function_name ] type_mark generic_map_aspect    -- new

If a generic_map_aspect is supplied in a subtype indication, the type_mark must denote a generic class type. The formal generic parameters that have to be mapped are defined by the effective generic list of the generic class type. The resulting subtype, for which all generics have specified values, is said to be a class subtype of the generic class type denoted by type_mark. A non-generic class type or a class subtype may be used in the first form in order to declare a resolved type.

Class types, class subtypes and class-wide types may be used in the declaration of

If the class type used in one of the above declarations is a generic class type, a generic map aspect must be provided. This implicitly declares an anonymous class subtype of the generic class type.

Note: the case of subtypes that has been present as a third point in a previous version of this document is now covered by the above paragraphs on subtyp_indication.

For composite types with elements of class type or class-wide type, no predefined relational operators (equality and inequality) exist.

Rationale: Equality is not predefined for class types and class-wide types because it would break their encapsulation.

Note: Since it is not possible to declare a range of a class type, subtyping cannot be used to restrict the value set of a class type. It remains the use of subtyping for declaration of resolved types.

Example: See declaration of type MemDataType in entity Memory (section 3.2.2).

4.5.2 Object declarations

A class type or class subtype that is not declared as abstract as well as any class-wide type may be used in the subtype indication of a

If the class type used in one of the above declarations is a generic class type, a generic map aspect must be provided. This implicitly declares an anonymous class subtype of the generic class type.

Note: Similarity to constraining unconstrained array type declarations in an object declaration.

With each VHDL object or interface object of class-wide type, information (called tag) on its actual class type is managed. The actual class type must be one out of the set of types denoted by the class-wide type. It is determined in the simulation (cf. 4.6.2) and represents the concrete type of the value contained by the VHDL object of class-wide type.

When a class-wide type is used in any of the above declarations, an initial value expression must be given to define the initial value of the declared VHDL object; it is an error if not. The initial value of a VHDL object of class type is--if not given explicitly by an expression--determined by the initial values of its class attributes, which is:

Note: A class attribute of a class-wide type must have an initial value expression. A class attribute is not a VHDL object, but VHDL objects can be declared using class types. Hence, the initial value of the attributes must be defined to be able to define the initial value of the VHDL object.

An access type to a class type, class subtype or to a class-wide type may be used in the subtype indication of a variable declaration (this includes shared variables). The initial value of such variable is null.

The evaluation of an allocator is permitted with a class type, class subtype or class-wide type. In case of a class-wide type, a qualified expression must be given with the allocator to determine its initial value. The initial value of an allocated object of class type is--in absence of a qualified expression--its default initial value (see above).

Drivers: For each process that invokes (by direct or indirect call) with a signal of class type or class-wide type a subprogram which potentially makes an assignment to a class attribute, a driver is created for the whole signal. In case of multiple drivers to a signal, the class type must be resolved globally by a resolution function (i.e. there is no resolution of the single class attributes).

Parameter passing: Parameters (VHDL interface objects) of class type or class-wide type are handled in analogy to record parameters of the respective mode, regarding parameter passing mechanisms and mode; i.e. class attributes of classes passed as input parameter must not be modified and class attributes of classes passed as output parameter must not be read.

4.6 Use of class instances

4.6.1 Subprogram call

Anchor: A subprogram of a class can be invoked with a prefix that has the type or the class-wide type or a class subtype of the class. The prefix may be an indexed name, a selected name, a simple name, or a function call.

Dynamic binding: In case of a class-wide type, the subprogram to be executed is selected from the class which is denoted by the actual type tag of the class.

procedure_call ::=
		  procedure_name [ ( actual_parameter_part ) ]											-- VHDL
		| prefix . class_procedure_name [ ( actual_parameter_part ) ]											-- new
function_call ::=
		  function_name [ ( actual_parameter_part ) ]											-- VHDL
		| prefix . class_function_name [ ( actual_parameter_part ) ]											-- new

If the prefix denotes a constant, the class procedure name (class function name, resp.) must denote a procedure (function, resp.) declared implicitly or explicitly in the common declarative region of the class type declaration alone (i.e. without the class body).

If the prefix denotes a signal, the class procedure name (class function name, resp.) must denote a procedure (function, resp.) declared implicitly or explicitly in the signal-specific declarative region of the class type declaration alone (i.e. without the class body).

If the prefix denotes a variable, the class procedure name (class function name, resp.) must denote a procedure (function, resp.) declared implicitly or explicitly in the variable-specific declarative region of the class type declaration alone (i.e. without the class body).

If the prefix denotes a class attribute, i.e. the call is from within a class body, the following rules apply:

Prefix THIS: The name THIS is implicitly declared in each class type declaration, derived class type declaration, and class type body. When a subprogram call prefixed with THIS is inherited by any derived class, and a redeclared version of the called subprogram exists in the derived class, this redeclared subprogram will be executed in the derived class instead of the subprogram originally called in the parent class.

4.6.2 Assignment

Static compatibility: Three levels of static compatibility are defined for class types and class-wide types. The set of types denoted by a class-wide type T'CLASS includes T and all the descendants of T. The set of types denoted by a class type T includes only the type T itself. A target of an assignment is said to be

Note: Compatibility can be expressed in terms of the ancestor relationship as shown in the table below, where T and E are class types:

TABLE 1. Assignment compatibility

target type

compatibility

expression type

E

E'CLASS

T

definite

T equal E

n/a

potential

n/a

E ancestor of T or equal

incompatible

others

others

T'CLASS

definite

T ancestor of E or equal

T ancestor of E or equal

potential

n/a

E ancestor of T

incompatible

others

others (i.e. not related)

Dynamic compatibility: An expression of a class-wide type is said to be dynamically compatible with the target of the assignment if the expression's actual class type is in the set of types denoted by the type of the target.

Note: Dynamic compatibility decides at simulation time whether a potentially compatible assignment works or fails.

Variable assignment: In the assignment of the value of an expression to a target variable, where class types or class-wide types are involved, the target's type must be definitely or potentially compatible with the expression's type. It is an error if the types are incompatible.

An assignment of an expression to a variable of class type or class-wide type is executed as follows: If the variable's type is not actually compatible with the expression, an error occurs during simulation. Otherwise the assignment is performed as follows.

Signal assignment: In the assignment of a waveform to a target signal, where class types or class-wide types are involved, the target's type must be definitely or potentially compatible with the types of each of the expressions occurring in the assigned waveform. It is an error if at least one of the types are incompatible.

An assignment of a waveform element to a signal of class type or class-wide type is executed as follows: If the signals type is not actually compatible with the expression of the waveform element, an error occurs during simulation. Otherwise the assignment is performed:

Example: Use of class types Number and Complex.

entity E is
		signal N			: Number;
		variable Nc			: Number'CLASS := CreateComplexValue( -1.1, 9.99 );
		variable C			: Complex;
		signal Cc			: Complex'CLASS := CreateComplexValue( 0.0, 0.0 );
begin
		process
		begin
			N <= Nc;		-- potentially compatible
			Nc := N;		-- definitely compatible
			Nc := C;		-- definitely compatible
			Nc := Cc;		-- definitely compatible
			C := Nc;		-- potentially compatible
			C := Cc;		-- potentially compatible
			Cc <= Nc;		-- potentially compatible
			Cc <= C;		-- definitely compatible
			-- other combinations are incompatible for assignment
			C.add( Nc, Nc );	  -- call to procedure add declared in class Complex
			Cc.add( Nc, Nc ); -- call to procedure add of the class denoted by
							-- the type tag of Cc (actual class type).
		end process;
end;

4.7 Lexical elements

The reserved words class and abstract are added to the list of reserved words in section 13.9 of the LRM.

4.8 Predefined language environment

4.8.1 Predefined type

An enumeration type universal_TAG is predefined. The type tags corresponding to the class types and representing the actual class type of class-wide values are of the type universal_TAG.

4.8.2 Predefined attributes

To avoid run-time errors caused by assignments of class objects of not actually compatible type (see 4.6.2) an attribute TAG is predefined which allows to query the actual class type of variables and signals of class type or class-wide type as well as of class types. By comparison of tags the compatibility for assignment can be checked.

Predefined attributes:

T'CLASS
		Kind :			Type.
		Prefix :			class type T
		Result Type :			type definition
		Result :			the class-wide type including T and its subclasses
T'TAG
		Kind :			Value.
		Prefix :			class type T
		Result Type :			universal_TAG
		Result :			the type tag corresponding to the class type
S'TAG
		Kind :			Function.
		Prefix :			signal of a class type or class-wide type
		Result Type :			universal_TAG
		Result :			if S is class-wide: current value of its actual type tag
					if S is class: the type tag corresponding to its class type
V'TAG
		Kind :			Function.
		Prefix :			variable of a class type or class-wide type
		Result Type :			universal_TAG
		Result:			if V is class-wide: current value of its actual type tag
					if V is class: the type tag corresponding to its class type
C'TAG
		Kind :			Function.
		Prefix :			constant of a class type or class-wide type
		Result Type :			universal_TAG
		Result:			if C is class-wide: current value of its actual type tag
					if C is class: the type tag corresponding to its class type

Note: Standard VHDL attributes, for instance 'EVENT or 'ACTIVE, are as well defined for signals of class type and class-wide type.

4.8.3 Predefined functions

For comparison of the class type tags the following relations are defined:

function "=" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;
function "/=" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;
function "<" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;
function ">" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;
function "<=" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;
function ">=" ( anonymous, anonymous : universal_TAG ) return BOOLEAN;

The semantics for the defined relations, where A and B are of type universal_TAG are:

A = B is TRUE iff A is the same type tag as B,
A /= B is TRUE iff A = B is FALSE,
A < B is TRUE iff A is ancestor of B,
A > B is TRUE iff B < A is TRUE (i.e. B is ancestor of A),
A <= B is TRUE iff A < B or A = B is TRUE,
A >= B is TRUE iff A > B or A = B is TRUE.


[1] The properties of a class attribute differ from classic VHDL attributes. Since the values of the class attributes are individual to each instance of the class, they should also be distinguished from the C++ static data fields which are often called class attributes.
[2] i.e. objects stored in signals, variables, or constants